package com.hzgj.bcl.soa.command;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.hzgj.bcl.soa.ws.ServiceRelation;
import com.hzgj.bcl.util.IocContext;
import com.hzgj.bcl.util.lang.StrKit;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;
import java.util.Set;

import static com.hzgj.bcl.soa.command.CommandsInitializer.RELATION_COMMAND;

public class RelationCommand implements SoaCommand {

    private ServiceRelation serviceRelation;

    @Override
    public String invoke(CommandOptions commandOptions) {
        String[] _service = commandOptions.params.get("service");
        String[] secondCommand = commandOptions.params.get(SoaCommand.secondCommand);
        if (StrKit.notBlank(secondCommand)) {
            switch (secondCommand[0]) {
                case "methods":
                    return methods(_service);
                default:
                    return defaultOp(_service);
            }
        } else {
            return defaultOp(_service);
        }
    }

    String methods(String _service[]) {
        if (_service != null) {
            return JSON.toJSONString(serviceRelation.getMethod(_service[0]));
        }
        return "";
    }

    String defaultOp(String _service[]) {
        if (_service == null) {
            return JSON.toJSONString(serviceRelation.getJstree());
        } else {
            ServiceRelation.Node node = serviceRelation.getNode(_service[0]);
            return buildVisjsData(node);
        }
    }

    @Override
    public void start() {
        serviceRelation = IocContext.applicationContext.getBean(ServiceRelation.class);
    }

    @Override
    public String getName() {
        return RELATION_COMMAND;
    }

    String buildVisjsData(ServiceRelation.Node node) {

        VisToplo visToplo = new VisToplo();
        buildOut(node.getOuts(), node, visToplo);
        buildIn(node.getIns(), node, visToplo);
        visToplo.nodes.add(new VisNode(node.getName(), node.getName()));
        return JSON.toJSONString(visToplo);
    }

    private void buildOut(Set<ServiceRelation.Node> nodes, ServiceRelation.Node parent, VisToplo visToplo) {
        nodes.forEach(node -> {
            visToplo.nodes.add(new VisNode(node.getName(), node.getName()));
            visToplo.edges.add(new VisEdge(parent.getName(), node.getName()));
            buildOut(node.getOuts(), node, visToplo);
        });
    }

    private void buildIn(Set<ServiceRelation.Node> nodes, ServiceRelation.Node child, VisToplo visToplo) {
        nodes.forEach(node -> {
            visToplo.nodes.add(new VisNode(node.getName(), node.getName()));
            visToplo.edges.add(new VisEdge(node.getName(), child.getName()));
            buildIn(node.getIns(), node, visToplo);
        });
    }

    @AllArgsConstructor
    @Getter
    static class VisNode {
        String id;
        String label;
    }

    @AllArgsConstructor
    @Getter
    static class VisEdge {
        String from;
        String to;
    }

    @Getter
    static class VisToplo {
        public List<VisNode> nodes = Lists.newArrayList();
        public List<VisEdge> edges = Lists.newArrayList();
    }

}
